# -*- coding: utf-8 -*-
import pystore.lib.libgmail.libgmail as libgmail

class MailClientGmailImpl:
    """
    先login(),后使用
    
    Gmail中，一般情况下只要邮件的subject相同，便放入同一个Thread
    但有一个特例:如果自己给自己发送邮件，subject即便相同也被列为不同的Thread，
    因为本程序用自己的账号给自己发文件，出于不要引起混乱的考虑，不应该考虑利用Thread特性。
    """
    
    def __init__(self):
        """arg gmailAccount : libgmail.GmailAccount"""
        self.gmailAccount=None
    
    def login(self,username,password):
        """
        return boolean  isSuccess
            if success: return True
            esle: return False 
        """
        try:
            self.gmailAccount=libgmail.GmailAccount(username,password)
            self.gmailAccount.login()
        except libgmail.GmailLoginFailure:
            print 'login error'
            return False
        print 'Gmail login ok.'
        self.username=username
        self.password=password
        return True
    
    def _clear(self):
        """clear all threads"""
        threads = self.gmailAccount.getMessagesByQuery('')
        for thread in threads:
            print 'Gmail clear...' ,thread.id, thread.subject
            self.gmailAccount.trashThread(thread)

    def send(self,mailId,fromFiles):
        """
         发送一个邮件,此邮件包含fromFiles指定的所有附件
        raise SendError : send error , i dont know reason
        raise SendErrorDuplicateSubjectAndFile: send error because Duplicate send
        """
        print 'Gmail send...' ,mailId,fromFiles
        
        #因为同subject同内容的邮件不能正常发送，所以加一个当前时间来让所有邮件都不重复
        #丛而保证不会发送失败
        msssage=libgmail.GmailComposedMessage(to=self.username,
            subject='[pyStore]:%s:%s' % (mailId,str(time.clock())) , 
            body=None,
            filenames=fromFiles,
            #files=map(open,fromFiles)
            )
        try:
            resultMsg = self.gmailAccount.sendMessage(msssage)
        except libgmail.GmailError ,e:
            print e
            raise SendError(mailId,fromFiles,str(e))
        
        if not resultMsg :
            raise SendError(mailId,fromFiles)
        
        #在同一进程中，同subject同内容的邮件将发送失败
        if resultMsg.id=='0':
            raise SendErrorDuplicateSubjectAndFile(mailId,fromFiles)
    
    def read(self,mailId):
        """
           read all files by id
           return list : file Content list
           return empty list: if not find        
        """
        print 'Gmail read...' ,mailId
        result=[]
        for attachment in self.__readAttachments(mailId):
            result.append(attachment.content)
        return result
    
    def readFromIndex(self,mailId,index):
        """
        readFromIndex(self,str mailId,int index) -> str
        
        mailId : 
        index : attachment index
        
        read one file by id and index
        """
        print 'Gmail read from index...' ,mailId,index
        return self.__readAttachments(mailId)[index].content
    
    def walkFirstAttachment(self,walkCallback):
        """
        walkFirstAttachment(self,WalkCallback walkCallback)
        
         遍历所有邮件的第一个附件,因为第一个附件存储文件树xml
        args:
          walkCallback: WalkCallback(str content) -> bool
              return bool isContinue , if False Stop walk
            
        """
        #all threads
        threads = self.__getAllPyStroeThreads()
        for thread in threads:
            for msg in thread:
                    if not walkCallback(msg.attachments[0].content):
                        return 

    def removeAll(self,mailId):
        """删除匹配mailId的所有邮件"""
        threads = self.__getThreadsByFileId(mailId,allPages = True)
        for thread in threads:
            print 'Gmail removeAll...' ,mailId,thread.id,thread.subject
            self.gmailAccount.trashThread(thread)
    
    def removeAllOld(self,mailId):
        """del all old thread,but first (first is newly)"""
        threads = self.__getThreadsByFileId(mailId,allPages = True)
        for threadIndex in range(len(threads)):
            if threadIndex ==0: continue
            print 'Gmail removeAllOld...' ,mailId
            self.gmailAccount.trashThread(threads[threadIndex])

    def exists(self,mailId):
        return self.count(mailId)>0
        
    def count(self,mailId):
        """
        count(self,mailId) -> int 
           
         返回同样id的邮件有多少封
        """
        threads = self.__getThreadsByFileId(mailId,allPages = False)
        return len(threads)
        
    def __getThreadsByFileId(self,mailId,allPages = False):
        """
        __getThreadsByFileId(self,str mailId,bool allPages = False) -> libgmail.GmailSearchResult
        
        """
        
        query='subject:%s has:attachment' % (mailId)
        return self.gmailAccount.getMessagesByQuery(query,allPages = allPages)
    
    def __getAllPyStroeThreads(self):
        query='subject:%s has:attachment' % ('[pystore]')
        return self.gmailAccount.getMessagesByQuery(query,allPages = True)
 
    def __readAttachments(self,mailId):
        threads = self.__getThreadsByFileId(mailId)
        for thread in threads:
            for msg in thread:
                    return msg.attachments
        return []
